package Java工具收集;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;

import Java基础.IO包深入解析.PathUtils;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;


public class FileUtils {
	
	/**
	 * @function 解密文件
	 * @author 肖荣辉
	 * @throws Exception 
	 * @date 2023年5月29日
	*/
	public static void desUnSecretFile(String filePath)  {
		
		try {
			
			filePath = filePath.indexOf("\\") != -1 ? filePath.replaceAll("\\\\", "/") : filePath;
			String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
			String parentDirPath = filePath.substring(0 , filePath.lastIndexOf("/")) + "/";
			String suffix = FileUtil.getSuffix(fileName);
			
			String outPath = parentDirPath + (suffix != null ? fileName.substring(0 , fileName.indexOf(".")) + "-unsecret." +  suffix : fileName + "-unsecret");
			
			String key = "+spnPjbNbdZdibsmiOFDqA==";
			
			FileInputStream fis = new FileInputStream(new File(parentDirPath +fileName));
			
			FileOutputStream fos = new FileOutputStream(new File(outPath));
			
			//解密文件
			SecureUtil.des(Base64.decode(key)).decrypt(fis, fos, true);
			
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * @function 加密文件
	 * @author 肖荣辉
	 * @throws Exception 
	 * @date 2023年5月29日
	*/
	public static void desSecretFile(String filePath)  {
		
		try {
			filePath = filePath.indexOf("\\") != -1 ? filePath.replaceAll("\\\\", "/") : filePath;
			String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
			String parentDirPath = filePath.substring(0 , filePath.lastIndexOf("/")) + "/";
			String suffix = FileUtil.getSuffix(fileName);
			String outPath = parentDirPath + (suffix != null ? fileName.substring(0 , fileName.indexOf(".")) + "-secret." +  suffix : fileName + "-secret");
			String key = "+spnPjbNbdZdibsmiOFDqA==";
			FileInputStream fis = new FileInputStream(new File(parentDirPath +fileName));
			FileOutputStream fos = new FileOutputStream(new File(outPath));
			SecureUtil.des(Base64.decode(key)).encrypt(fis, fos, true);
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * @function 根据json文件路径生成java文件
	 * @param jsonFilePath json文件路径
	 * @param java文件名称
	 * @param remarkSameWithPropertyName true : 注释和属性名一直 , false : unknown
	 * @author 肖荣辉
	 * @date 2023年1月31日
	*/
	public static void createBeanFile(String jsonFilePath , String beanFileName , boolean remarkSameWithPropertyName) {
		
		List<String> lines = FileUtil.readLines(jsonFilePath , "utf-8");
		
		List<String> explainList = new ArrayList<String>();
		
		StringBuilder sb = new StringBuilder();
		
		for(String str : lines) {
			
			if(StrUtil.isBlank(str))
				continue;
			
			sb.append(str.indexOf("//") != -1 ? str.substring(0 , str.indexOf("//")) : str);
			
			if(str.indexOf(":") == -1)
				continue;
			
			if(str.lastIndexOf("//") != -1) {
				explainList.add(StrUtil.trim(str.substring(str.lastIndexOf("//")).replaceAll("//", "")));	
			}else {
				explainList.add("");	
			}
		
		}
		
		JSONConfig config = JSONConfig.create();
		
		config.setOrder(true);
		config.setIgnoreNullValue(false);
		
		JSONObject row = JSONUtil.parseObj(sb.toString(), config);
		
		Set<String> keys = row.keySet();
		
		Map<String , String> keyExplainMap = new HashMap<String, String>();
		
		int i = 0 ; 
		
		for(String key : keys) {
			keyExplainMap.put(key, i >= explainList.size() ? "" : explainList.get(i));
			i++;
		}
		 
		Object[] keyArr = keys.toArray();
		
		//总是按字典序
		 Arrays.sort(keyArr);
		 
		 String txt = "package com.sy.gcp.ward.service.service.hospital.impl.nanjinggulou.beans;\r\n\r\n" + 
					 		 "import io.swagger.annotations.ApiModelProperty;\r\n" + 
					 		 "import lombok.Data;\r\n\r\n" + 
					 		 "@Data\r\n" + 
					 		 "public class "+StrUtil.upperFirst(beanFileName)+" {\r\n\r\n";
		 
         for(Object key : keyArr) {
        	 String explain = keyExplainMap != null  ? keyExplainMap.get(key) : "";
        	 explain = remarkSameWithPropertyName ? key.toString() : explain;
        	 txt+= "\t@ApiModelProperty(\""+(StrUtil.isBlank(explain) ? "unknow" : StrUtil.trim(explain) )+"\")\r\n";
        	 txt+= "\tprivate String " + key.toString() + ";\r\n\r\n";
         }
         
         txt += "}";
         
         beanFileName = StrUtil.isBlank(beanFileName) ? "unname.java" : beanFileName + ".java"; 
         
         String filePath = PathUtils.getDesktopPath() + File.separator  + beanFileName;
         
         System.out.println("生成java文件到 :" +  filePath);
         
         try {
			saveTxtFile(filePath , txt);
		} catch (IOException e) {
			System.out.println("生成java文件到 ："+filePath + "错误 ，" + e.getMessage()  );
		}
         
	}
	
	/**
	 * @function 根据文本生成文件
	 * @author ronghui.xiao
	 * @throws IOException 
	 * @date 2017年6月21日
	 */
	public static File saveTxtFile(String path , String txt) throws IOException{
	
		File file = new File(path);
		file.mkdirs();  //创建父级目录
		
		//若存在则删除
		if(file.exists()) file.delete();
		
		file.createNewFile();
		
		Writer fileWriter = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file), "UTF-8"));  
		        
		fileWriter.write(txt);
		fileWriter.close();
		
		return file;
	}
	
	/**
	* @function 保存属性文件
	* @param properties
	* @param filePath
	* @author 肖荣辉
	* @date 2018年9月12日
	*/
	public static void saveProperties(Properties properties , String filePath) throws IOException{
		FileOutputStream fos = new FileOutputStream(filePath);
		properties.store(fos, null);
		fos.close();
	}
	
	/**
	* @function 读取属性文件
	* @param filePath 文件路径
	* @author 肖荣辉
	 * @throws IOException 
	 * @throws FileNotFoundException 
	* @date 2018年9月12日
	*/
	public static Properties readProperties(String filePath) throws FileNotFoundException, IOException{
		
		Properties properties = new Properties();
		FileInputStream fis = new FileInputStream(filePath);
		properties.load(fis);
		fis.close();
		
		return properties;
	}
	
	/**
	 * 读取文本文件
	 * @throws IOException 
	 */
	public static String readFileToString(String filePath , String encoding) throws IOException{
		
		File file = new File(filePath);
		
		FileInputStream fis = new FileInputStream(file);
		
		InputStreamReader isr = new InputStreamReader(fis , encoding);
		
		BufferedReader br = new BufferedReader(isr);
		
		String temp = null;
		
		StringBuilder sb = new StringBuilder();
		
		while((temp = br.readLine()) != null){
			 sb.append(temp).append("\n");
		}
		
		br.close();
		
		return sb.toString();
		
	}
	
	/**
	 * 读取文本文件
	 * @throws IOException 
	 */
	public static String readFileToString(String filePath) throws IOException{
		
		File file = new File(filePath);
		
		FileInputStream fis = new FileInputStream(file);
		
		InputStreamReader isr = new InputStreamReader(fis);
		
		BufferedReader br = new BufferedReader(isr);
		
		String temp = null;
		
		StringBuilder sb = new StringBuilder();
		
		while((temp = br.readLine()) != null){
			 sb.append(temp).append("\n");
		}
		
		br.close();
		
		return sb.toString();
		
	}
	
	
	/**
	 * 读取文本文件
	 * @throws IOException 
	 */
	public static String readFileToString(InputStream is) throws IOException{
		
		InputStreamReader isr = new InputStreamReader(is);
		
		BufferedReader br = new BufferedReader(isr);
		
		String temp = null;
		
		StringBuilder sb = new StringBuilder();
		
		while((temp = br.readLine()) != null){
			 sb.append(temp).append("\n");
		}
		
		br.close();
		
		return sb.toString();
		
	}
	
	/**
	* @function 根据包路径获取文本文件字节数组
	* @param relativePath 相对路径
	* @author 肖荣辉
	 * @throws IOException 
	* @date 2018年9月14日
	*/
	public static byte[] readFileByRelativePath(String relativePath) throws IOException{
		ClassPathResource cpr = new ClassPathResource(relativePath);
	 	byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
	 	return bdata;
	}
	
	
	/**
	* @function 根据包路径获取文本文件
	* @author 肖荣辉
	* @param relativePath 相对路径
	* @param encoding 编码
	 * @throws IOException 
	* @date 2018年9月14日
	*/
	public static String readFileToStringByRelativePath(String relativePath , String encoding) throws IOException{
		return new String(readFileByRelativePath(relativePath) , Charset.forName(encoding));
	}
	
	/**
	* @function 替换文本文件中的标记字符串
	* @param filePath 文件路径
	* @param replaceCofig 需要替换的字符串配置 key : 要被替换的标记 , value : 要替换的字符串
	* @author 肖荣辉
	 * @throws IOException 
	* @date 2018年9月12日
	*/
	public static void replaceTextFileMarkString(String filePath , Map<String , String> replaceCofig , String encoding) throws IOException{
		
		String content = readFileToString(filePath , encoding);
		
	    Set<Map.Entry<String , String>> entrySet = replaceCofig.entrySet();
		
	    for(Map.Entry<String , String> item : entrySet){
	    	content = content.replaceAll(item.getKey(), item.getValue());
	    }
	    save2disk(content.getBytes(encoding) , filePath);
	    
	}
	
	/**
	* @function 替换文本文件中的标记字符串
	* @param filePath 文件路径
	* @author 肖荣辉
	 * @throws IOException 
	* @date 2018年9月12日
	*/
	public static void replaceTextFileMarkString(String filePath , String oldStr , String newStr  , String encoding) throws IOException{
		
		String content = readFileToString(filePath , encoding);
		
		content = content.replaceAll(oldStr , newStr);
		
	    save2disk(content.getBytes(encoding) , filePath);
	    
	}
	
	/**
	* @function 保存到磁盘
	* @author 肖荣辉
	* @date 2018年8月1日
	*/
	public static void save2disk(byte[] data , String filePath ) throws IOException{
	
		File file = new File(filePath);
		file.mkdirs();  
		
		file = new File(filePath);
		
		//若存在则删除
		if(file.exists()) file.delete();
		
		file.createNewFile();
		
		ByteArrayInputStream bis = new ByteArrayInputStream(data);
		
		FileOutputStream fos = new FileOutputStream(file);
		
		byte[] buff = new byte[1024];
		
		int len;
		
		while((len = bis.read(buff)) != -1){
			fos.write(buff , 0 , len); 
		}
		
		fos.close();
		
	}
	
	/**
	* @function 修改目录名称
	* @param parentDirPath 父目录路径
	* @param oldName 老的文件名
	* @param newName 新名称
	* @author 肖荣辉
	* @date 2018年11月11日
	* 注意 : 重命名的时候,名称不能有空格,否则会报错
	*/
	public static void renameFile(String parentDirPath , String oldName , String newName){
		
		File file = new File(parentDirPath + File.separator + oldName);
		
		if(!file.exists()) return;
		
		File newFlie = new File(parentDirPath + File.separator + newName);
		
		file.renameTo(newFlie);
		
	}
	
	/**
	 * @function 根据文本生成文件
	 * @author ronghui.xiao
	 * @throws IOException 
	 * @date 2017年6月21日
	 */
	public static File generateFile(String path , String fileName , String txt) throws IOException{
	
		File file = new File(path);
		file.mkdirs();  //创建父级目录
		
		String filePath = path  + File.separator + fileName ;
		
		file = new File(filePath);
		
		//若存在则删除
		if(file.exists()) file.delete();
		
		file.createNewFile();
		
		Writer fileWriter = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file), "UTF-8"));  
		        
//		FileWriter fileWriter = new FileWriter(file);
		fileWriter.write(txt);
		fileWriter.close();
		
		return file;
	}
	
	/**
	* @function 删除文件夹下所有文件路径
	* @param folderPath 文件夹路径
	* @author 肖荣辉
	* @date 2018年9月12日
	*/
    public static void delFolder(String folderPath) {
        delAllFile(folderPath); 
        File myFilePath = new File(folderPath);
        myFilePath.delete(); 
	}

	/**
	* @function 删除文件夹下所有文件路径
	* @param path 文件夹路径
	* @author 肖荣辉
	* @date 2018年9月12日
	*/
   public static boolean delAllFile(String path) {
	   
	       boolean flag = false;
	       
	       File file = new File(path);
	       
	       if (!file.exists())  return flag;
	       
	       if (!file.isDirectory()) return flag;
	       
	       String[] tempList = file.list();
	       File temp = null;
	       
	       for (int i = 0; i < tempList.length; i++) {
	    	   
	          if (path.endsWith(File.separator)) {
	             temp = new File(path + tempList[i]);
	          } else {
	              temp = new File(path + File.separator + tempList[i]);
	          }
	          
	          if (temp.isFile())  temp.delete();
	          
	          if (temp.isDirectory()) {
	        	  //先删除文件夹里面的文件
	             delAllFile(path + "/" + tempList[i]);
	             //再删除空文件夹
	             delFolder(path + "/" + tempList[i]);
	             flag = true;
	          }
	       }
	       
	       return flag;
     }
   
}
